`timescale 1ns/1ns
`define DELAY 20
module alu_test;
    wire [7 : 0] out;
    reg [7 : 0] data, accum;
    reg [2 : 0] opcode;
    // integer i;
    wire zero;
    parameter   PASS0 = 3'B000,
                PASS1 = 3'B001,
                ADD   = 3'B010,
                AND   = 3'B011,
                XOR   = 3'B100,
                PASSD = 3'B101,
                PASS6 = 3'B110,
                PASS7 = 3'B111;
    alu a1 (
        .out(out),
        .zero(zero),
        .opcode(opcode),
        .data(data),
        .accum(accum)
    );

    initial begin
        $display("<------------INPUTS------------><-OUTPUTS->");
        $display("  TIME    OPCODE  DATA IN  ACCUM IN  ALU OUT  ZERO BIT");
        $display("--------- -----   -------- --------  -------- --------");
        $timeformat(-9, 1, "ns", 9);
        $dumpvars(2, alu_test);
    end

    task expect;
    input [8 : 0] expects;
    begin
        $display("%t %b     %b %b  %b %b", $stime, opcode, data, accum, out, zero);
        if ({zero, out} != expects) begin
            $display("TEST FAILED");
            $finish;
        end
    end
    endtask

    initial begin
        {opcode, accum, data} = {PASS0, 8'H00, 8'Hff}; #(`DELAY) expect({1'B1, accum});
        {opcode, accum, data} = {PASS0, 8'H55, 8'Hff}; #(`DELAY) expect({1'B0, accum});
        {opcode, accum, data} = {PASS1, 8'H55, 8'Hff}; #(`DELAY) expect({1'B0, accum});
        {opcode, accum, data} = {PASS1, 8'Hcc, 8'Hff}; #(`DELAY) expect({1'B0, accum});
        {opcode, accum, data} = {ADD  , 8'H33, 8'Haa}; #(`DELAY) expect({1'B0, accum + data});
        {opcode, accum, data} = {AND  , 8'H0f, 8'H33}; #(`DELAY) expect({1'B0, accum & data});
        {opcode, accum, data} = {XOR  , 8'Hf0, 8'H55}; #(`DELAY) expect({1'B0, accum ^ data});
        {opcode, accum, data} = {PASSD, 8'H00, 8'Haa}; #(`DELAY) expect({1'B1, data});
        {opcode, accum, data} = {PASSD, 8'H00, 8'Hcc}; #(`DELAY) expect({1'B1, data});
        {opcode, accum, data} = {PASS6, 8'Hff, 8'Hf0}; #(`DELAY) expect({1'B0, accum});
        {opcode, accum, data} = {PASS7, 8'Hcc, 8'H0f}; #(`DELAY) expect({1'B0, accum});
        $display("TEST PASSED");
        $finish;
    end
endmodule
